Date: Tue Mar 24 12:26:08 2020
Scientist: Ran Yin
Sequencing (Waksman): Dibyendu Kumar
Statistics: Davit Sargsyan
Principal Investigator: Ah-Ng Kong

# Taxonomic Ranks:
# **K**ing **P**hillip **C**an n**O**t **F**ind **G**reen **S**ocks
# * Kingdom                
# * Phylum                    
# * Class                   
# * Order                   
# * Family     
# * Genus     
# * Species  
options(stringsAsFactors = FALSE,
        scipen = 999)
# # Increase mmemory size to 64 Gb----
# invisible(utils::memory.limit(65536))
# str(knitr::opts_chunk$get())
# # NOTE: the below does not work!
# knitr::opts_chunk$set(echo = FALSE, 
#                       message = FALSE,
#                       warning = FALSE,
#                       error = FALSE)
# require(knitr)
# require(kableExtra)
# require(shiny)
require(phyloseq)
require(data.table)
require(ggplot2)
require(plotly)
require(DT)
source("source/functions_may2019.R")
# On Windows set multithread=FALSE----
mt <- TRUE

1 Introduction

C57BL/6 wild-type (WT) and Nrf-2 double-knock-out (KO -/-) mice were given 2-week microbiome stabilization process using AIN93M diet and 8 more weeks to treat with either AIN93M or AIN93M 5% PEITC diet. Fecal samples were collected weekly, immediately frozen in liquid nitrogen and stored at -80oC. Serum, cecal, colon epithelial and whole colon tissues at week 10 were also collected for further analyses. Baseline, week 1 and 4 fecal samples were selected for 16s rRNA sequencing.

This document examines results from the WT mice samples.

We will attampt to answer the following questions:
1. Did microbiome change over time?
2. Was microbiome affected by diet?
3. Was there a difference between the KO and WT?
4. If there was a change in microbiome composition, what functional changes did it carry? What are the essential functions of the bacteria affected by the treatment and how can this be shown in vivo (metabolites, inflammation markers, etc.)?

2 Data preprocessing

2.1 Raw Data

FastQ files were downloaded from Dr. Kumar’s DropBox. A total of 60 files (2 per sample, pair-ended) and 2 metadata files were downloaded.

2.2 Script

This script (nrf2ubiome_dada2_may2019_v1.Rmd) was developed using DADA2 Pipeline Tutorial (1.12) with tips and tricks from the University of Maryland Shool of Medicine Institute for Genome Sciences (IGS) Microbiome Analysis Workshop (April 8-11, 2019). The output of the DADA2 script (data_may2019/ps_may2019.RData) is explored in this document.

3 Meta data: sample description

# Load data----
# Counts
load("data_may2019/ps_may2019.RData")
# Taxonomy
load("data_may2019/taxa.RData")
taxa <- data.table(seq16s = rownames(taxa),
                   taxa)
# Samples
samples <- ps_may2019@sam_data
datatable(samples,
              options = list(pageLength = nrow(samples)))

4 Prune data

The OTUs were mapped to Bacteria (98.34%), Eukaryota (1.43%) and undefined (0.23%) kingdoms.

The total of 8,129 unique sequences were found. Out of those, 7,994 were mapped to bacterial genomes.

dim(ps_may2019@otu_table@.Data)
[1]   30 8129
# Remove OTU unmapped to Bacteria
ps0 <- subset_taxa(ps_may2019, 
                   Kingdom == "Bacteria")
dim(ps0@otu_table@.Data)
[1]   30 7994

These belonged to 13 Phylum. 230 of the OTUs (or 2.88% of bacterial OTUs) could not be mapped to a Phyla and were removed from this analysis (with 7,764 OTUs left).

t2 <- data.table(table(tax_table(ps0)[, "Phylum"],
                                  exclude = NULL))
t2$V1[is.na(t2$V1)] <- "Unknown"
setorder(t2, -N)
t2[, pct := N/sum(N)]
setorder(t2, -N)
colnames(t2) <- c("Phylum",
                  "Number of OTUs",
                  "Percent of OTUs")
datatable(t2,
          rownames = FALSE,
          caption = "Number of Bacterial OTUs by Phylum",
          class = "cell-border stripe",
          options = list(search = FALSE,
                         pageLength = nrow(t2))) %>%
  formatCurrency(columns = 2,
                 currency = "",
                 mark = ",",
                 digits = 0) %>%
  formatPercentage(columns = 3,
                   digits = 2)

ps1 <- subset_taxa(ps0, 
                   !is.na(Phylum))
dim(ps1@otu_table@.Data)
[1]   30 7764

5 OTU table (first 10 rows)

6 Total counts per sample (i.e. sequencing depth)

tmp <- copy(smpl)
tmp$WEEK <- factor(tmp$WEEK,
                    levels = c("week 0",
                               "week 1",
                               "week 4"),
                    labels = c("Week 0",
                               "Week 1",
                               "Week 4"))

tmp$TREATMENT <- factor(tmp$TREATMENT,
                        levels = c("Control",
                                   "PEITC"),
                        labels = c("AIN93M",
                                   "PEITC"))
p1 <- ggplot(tmp,
             aes(x = SAMPLE_NAME,
                 y = Total,
                 group = TREATMENT,
                 fill = TREATMENT)) +
  facet_wrap(~ WEEK,
             scale = "free_x") +
  geom_bar(stat = "identity",
           color = "black") +
  scale_x_discrete("") +
  scale_y_continuous("Number of Reads") +
  scale_fill_grey("Treatment", 
                  start = 0.2, 
                  end = 0.8,
                  na.value = "red",
                  aesthetics = "fill") +
  theme_bw() + 
  theme(panel.border = element_blank(), 
        panel.grid.major = element_blank(),
        panel.grid.minor = element_blank(), 
        axis.title.x=element_blank(),
        axis.text.x=element_blank(),
        axis.ticks.x=element_blank(),
        legend.position = "top")

tiff(filename = "tmp/seq_depth_may2019.tiff",
     height = 4,
     width = 6,
     units = "in",
     res = 600,
     compression = "lzw+p")
print(p1)
graphics.off()

print(p1)

7 Richness (Alpha diversity)

Shannon’s diversity index was calculated for each sample and ploted over time using the 7,764 from the 13 Phylum above.

ps0@sam_data$Diet_Week <- paste(samples$TREATMENT,
                                samples$WEEK,
                                sep = "_")
ps0@sam_data$ID <- substr(x = ps0@sam_data$SAMPLE_NAME,
                          start = 2,
                          stop = 3)
p1 <- plot_richness(ps0,
                    x = "Diet_Week", 
                    measures = "Shannon") +
    geom_line(aes(group = ID),
            color = "black") +
  geom_point(aes(fill = ID),
             shape = 21,
             size = 3,
             color = "black") +
  scale_x_discrete("") +
  theme(axis.text.x = element_text(angle = 30,
                                   hjust = 1,
                                   vjust = 1))

ggplotly(p = p1,
         tooltip = c("ID",
                     "value"))

p1 <- p1 + theme(legend.position = "none")

tiff(filename = "tmp/wt_shannon.tiff",
     height = 4,
     width = 5,
     units = "in",
     res = 600,
     compression = "lzw+p")
print(p1)
graphics.off()
tmp <- data.table(p1$data)
tmp[, delta := value[WEEK == "week 4"] - 
      value[WEEK == "week 0"],
    by = ID]

tmp1 <- droplevels(unique(tmp[WEEK %in% c("week 0",
                                          "week 4"), 
                              c("value",
                                "WEEK",
                                "TREATMENT")]))
m1 <- lm(value ~ WEEK*TREATMENT,
         data = tmp1)
print("Model1: Shannon's index by treatment and time")
anova(m1)

tmp2 <- droplevels(unique(tmp[WEEK == "week 0", 
                              c("delta",
                                "value",
                                "TREATMENT")]))
m2 <- lm(delta ~ TREATMENT,
         data = tmp2)
print("Model2: Shannon's index differences (Week 4 - Week 0) by treatment")
anova(m2)

m3 <- wilcox.test(delta ~ TREATMENT,
            data = tmp2)
print("Model3: Wilcoxon test for Shannon's index differences (Week 4 - Week 0) by treatment")
m3

The results showed that in 4 out of 5 animals in the PEITC group diversity increased over the 4 weeks compared to the baseline. At the same time, only 2 out of 5 Control animals increased its microbial diversity in the same period of time. NOTE: there was no statistically significant difference between the treatment groups as well as over time (see results above).

8 Counts at Phylum level

9 Relative abundance (%) at Phylum level

Remove phyla with relative abundance of >= 1% in less than 10% of samples.

t1 <- data.table(Phylum = ra_p$Phylum,
                 `Number of Samples` = rowSums(ra_p[, 2:ncol(ra_p)] >= 0.01))
t1$`Percent Samples` <-  t1$`Number of Samples`/30

setorder(t1, -`Number of Samples`)
datatable(t1,
          rownames = FALSE,
          caption = "Taxonomic  count table",
          class = "cell-border stripe",
          options = list(search = FALSE,
                         pageLength = nrow(t1))) %>%
  formatPercentage(columns = 3,
                   digits = 1)

Hence, only 6 out of 13 Phyla were studied in this analysis: Actinobacteria, Bacteroidetes, Firmicutes, Proteobacteria, Tenericutes and Verrucomicrobia. Relative abundance at the next taxonomic level (Class) was, therefore, computed relative to the sum of these 6 Phyla.

7,628 OTUs, down from 7,764 OTUs in the previous table.

10 Relative Abundance in Samples at Different Taxonomic Ranks

10.1 1. Class

p0 <- ggplot(mu,
             aes(x = Week,
                 y = x,
                 group = Treatment)) +
  facet_wrap(~ Class,
             scale = "free_y") +
  geom_line() +
  geom_point(aes(shape = Treatment,
                 color = Treatment),
             size = 3,
             alpha = 0.5) +
  scale_x_discrete("") +
  scale_y_continuous("Relative Abundance (%)") +
  theme(legend.position = "top",
        axis.text.x = element_text(angle = 45,
                                   hjust = 1))

tiff(filename = "tmp/wt_class_over_time.tiff",
     height = 5,
     width = 7,
     units = "in",
     res = 600,
     compression = "lzw+p")
print(p0)
graphics.off()

print(p0)
p1 <- ggplot(mu,
             aes(x = x,
                 y = Class,
                 color = Treatment,
                 shape = Week)) +
  geom_point(size = 3,
             alpha = 0.5) +
  geom_vline(xintercept = 1,
             linetype = "dashed") +
  scale_x_continuous("Relative Abundance (%)") +
  theme(legend.position = "top")

tiff(filename = "tmp/wt_class_ra.tiff",
     height = 4,
     width = 7,
     units = "in",
     res = 600,
     compression = "lzw+p")
print(p1)
graphics.off()

ggplotly(p1)

10.2 2. Order

p0 <- ggplot(mu,
             aes(x = Week,
                 y = x,
                 group = Treatment)) +
  facet_wrap(~ Order,
             scale = "free_y") +
  geom_line() +
  geom_point(aes(shape = Treatment,
                 color = Treatment),
             size = 5,
             alpha = 0.5)
print(p0)
p1 <- ggplot(mu,
             aes(x = x,
                 y = Order,
                 fill = Treatment,
                 shape = Week)) +
  # facet_wrap(~ Sex, nrow = 1) +
  geom_point(size = 3,
             alpha = 0.5) +
  geom_vline(xintercept = 1,
             linetype = "dashed") +
  scale_x_continuous("Relative Abundance (%)")
ggplotly(p1)

11 Session Information

sessionInfo()
LS0tCnRpdGxlOiAiTnJmMiBCTDYgV2lsZC1UeXBlIChXVCkgUEVJVEMgMTZTIE1pY3JvYmlvbWUgRGF0YSBWaXN1YWxpemF0aW9uIgpvdXRwdXQ6IAogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHllcwogICAgdG9jX2Zsb2F0OiB5ZXMKICAgIG51bWJlcl9zZWN0aW9uczogeWVzCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKLS0tCkRhdGU6IGByIGRhdGUoKWAgICAgIApTY2llbnRpc3Q6IFtSYW4gWWluXShtYWlsdG86cnkxNDdAc2NhcmxldG1haWwucnV0Z2Vycy5lZHUpICAgICAgClNlcXVlbmNpbmcgKFdha3NtYW4pOiBbRGlieWVuZHUgS3VtYXJdKG1haWx0bzpka0B3YWtzbWFuLnJ1dGdlcnMuZWR1KSAgICAgIApTdGF0aXN0aWNzOiBbRGF2aXQgU2FyZ3N5YW5dKG1haWx0bzpzYXJnZGF2aWRAZ21haWwuY29tKSAgICAgIApQcmluY2lwYWwgSW52ZXN0aWdhdG9yOiBbQWgtTmcgS29uZ10obWFpbHRvOmtvbmd0QHBoYXJtYWN5LnJ1dGdlcnMuZWR1KSAKCmBgYHt9CiMgVGF4b25vbWljIFJhbmtzOgojICoqSyoqaW5nICoqUCoqaGlsbGlwICoqQyoqYW4gbioqTyoqdCAqKkYqKmluZCAqKkcqKnJlZW4gKipTKipvY2tzCiMgKiBLaW5nZG9tICAgICAgICAgICAgICAgIAojICogUGh5bHVtICAgICAgICAgICAgICAgICAgICAKIyAqIENsYXNzICAgICAgICAgICAgICAgICAgIAojICogT3JkZXIgICAgICAgICAgICAgICAgICAgCiMgKiBGYW1pbHkgICAgIAojICogR2VudXMgICAgIAojICogU3BlY2llcyAgCmBgYAoKYGBge3Igc2V0dXB9Cm9wdGlvbnMoc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFLAogICAgICAgIHNjaXBlbiA9IDk5OSkKCiMgIyBJbmNyZWFzZSBtbWVtb3J5IHNpemUgdG8gNjQgR2ItLS0tCiMgaW52aXNpYmxlKHV0aWxzOjptZW1vcnkubGltaXQoNjU1MzYpKQoKCiMgc3RyKGtuaXRyOjpvcHRzX2NodW5rJGdldCgpKQojICMgTk9URTogdGhlIGJlbG93IGRvZXMgbm90IHdvcmshCiMga25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBGQUxTRSwgCiMgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSBGQUxTRSwKIyAgICAgICAgICAgICAgICAgICAgICAgd2FybmluZyA9IEZBTFNFLAojICAgICAgICAgICAgICAgICAgICAgICBlcnJvciA9IEZBTFNFKQoKIyByZXF1aXJlKGtuaXRyKQojIHJlcXVpcmUoa2FibGVFeHRyYSkKIyByZXF1aXJlKHNoaW55KQoKcmVxdWlyZShwaHlsb3NlcSkKcmVxdWlyZShkYXRhLnRhYmxlKQpyZXF1aXJlKGdncGxvdDIpCnJlcXVpcmUocGxvdGx5KQpyZXF1aXJlKERUKQoKc291cmNlKCJzb3VyY2UvZnVuY3Rpb25zX21heTIwMTkuUiIpCgojIE9uIFdpbmRvd3Mgc2V0IG11bHRpdGhyZWFkPUZBTFNFLS0tLQptdCA8LSBUUlVFCmBgYAoKIyBJbnRyb2R1Y3Rpb24KQzU3QkwvNiB3aWxkLXR5cGUgKFdUKSBhbmQgTnJmLTIgZG91YmxlLWtub2NrLW91dCAoS08gLS8tKSBtaWNlIHdlcmUgZ2l2ZW4gMi13ZWVrIG1pY3JvYmlvbWUgc3RhYmlsaXphdGlvbiBwcm9jZXNzIHVzaW5nIEFJTjkzTSBkaWV0IGFuZCA4IG1vcmUgd2Vla3MgdG8gdHJlYXQgd2l0aCBlaXRoZXIgQUlOOTNNIG9yIEFJTjkzTSA1JSBQRUlUQyBkaWV0LiBGZWNhbCBzYW1wbGVzIHdlcmUgY29sbGVjdGVkIHdlZWtseSwgaW1tZWRpYXRlbHkgZnJvemVuIGluIGxpcXVpZCBuaXRyb2dlbiBhbmQgc3RvcmVkIGF0IC04MF5vXkMuIFNlcnVtLCBjZWNhbCwgY29sb24gZXBpdGhlbGlhbCBhbmQgd2hvbGUgY29sb24gdGlzc3VlcyBhdCB3ZWVrIDEwIHdlcmUgYWxzbyBjb2xsZWN0ZWQgZm9yIGZ1cnRoZXIgYW5hbHlzZXMuIEJhc2VsaW5lLCB3ZWVrIDEgYW5kIDQgZmVjYWwgc2FtcGxlcyB3ZXJlIHNlbGVjdGVkIGZvciAxNnMgclJOQSBzZXF1ZW5jaW5nLiAgCiAgClRoaXMgZG9jdW1lbnQgZXhhbWluZXMgcmVzdWx0cyBmcm9tIHRoZSBXVCBtaWNlIHNhbXBsZXMuICAKICAKV2Ugd2lsbCBhdHRhbXB0IHRvIGFuc3dlciB0aGUgZm9sbG93aW5nIHF1ZXN0aW9uczogIAoxLiBEaWQgbWljcm9iaW9tZSBjaGFuZ2Ugb3ZlciB0aW1lPyAgCjIuIFdhcyBtaWNyb2Jpb21lIGFmZmVjdGVkIGJ5IGRpZXQ/ICAKMy4gV2FzIHRoZXJlIGEgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBLTyBhbmQgV1Q/ICAKNC4gSWYgdGhlcmUgd2FzIGEgY2hhbmdlIGluIG1pY3JvYmlvbWUgY29tcG9zaXRpb24sIHdoYXQgZnVuY3Rpb25hbCBjaGFuZ2VzIGRpZCBpdCBjYXJyeT8gV2hhdCBhcmUgdGhlIGVzc2VudGlhbCBmdW5jdGlvbnMgb2YgdGhlIGJhY3RlcmlhIGFmZmVjdGVkIGJ5IHRoZSB0cmVhdG1lbnQgYW5kIGhvdyBjYW4gdGhpcyBiZSBzaG93biBpbiB2aXZvIChtZXRhYm9saXRlcywgaW5mbGFtbWF0aW9uIG1hcmtlcnMsIGV0Yy4pPwoKIyBEYXRhIHByZXByb2Nlc3NpbmcKIyMgUmF3IERhdGEgCkZhc3RRIGZpbGVzIHdlcmUgZG93bmxvYWRlZCBmcm9tIFtEci4gS3VtYXIncyBEcm9wQm94XShodHRwczovL3d3dy5kcm9wYm94LmNvbS9zaC9zbTl0aW5tMGY1cjZ5MXYvQUFEakdQUlJOaUlNN3pNU2ZBTkRrUWpGYT9kbD0wKS4gQSB0b3RhbCBvZiA2MCBmaWxlcyAoMiBwZXIgc2FtcGxlLCBwYWlyLWVuZGVkKSBhbmQgMiBtZXRhZGF0YSBmaWxlcyB3ZXJlIGRvd25sb2FkZWQuCgojIyBTY3JpcHQKVGhpcyBzY3JpcHQgKCoqKm5yZjJ1YmlvbWVfZGFkYTJfbWF5MjAxOV92MS5SbWQqKiopIHdhcyBkZXZlbG9wZWQgdXNpbmcgW0RBREEyIFBpcGVsaW5lIFR1dG9yaWFsICgxLjEyKV0oaHR0cHM6Ly9iZW5qam5lYi5naXRodWIuaW8vZGFkYTIvdHV0b3JpYWwuaHRtbCkgd2l0aCB0aXBzIGFuZCB0cmlja3MgZnJvbSB0aGUgW1VuaXZlcnNpdHkgb2YgTWFyeWxhbmQgU2hvb2wgb2YgTWVkaWNpbmUgSW5zdGl0dXRlIGZvciBHZW5vbWUgU2NpZW5jZXMgKElHUyldKGh0dHA6Ly93d3cuaWdzLnVtYXJ5bGFuZC5lZHUvKSBbTWljcm9iaW9tZSBBbmFseXNpcyBXb3Jrc2hvcCAoQXByaWwgOC0xMSwgMjAxOSldKGh0dHA6Ly93d3cuaWdzLnVtYXJ5bGFuZC5lZHUvZWR1Y2F0aW9uL3drc2hwX21ldGFnZW5vbWUucGhwKS4gVGhlIG91dHB1dCBvZiB0aGUgREFEQTIgc2NyaXB0ICgqKipkYXRhX21heTIwMTkvcHNfbWF5MjAxOS5SRGF0YSoqKikgaXMgZXhwbG9yZWQgaW4gdGhpcyBkb2N1bWVudC4KCiMgTWV0YSBkYXRhOiBzYW1wbGUgZGVzY3JpcHRpb24KYGBge3IgZGF0YX0KIyBMb2FkIGRhdGEtLS0tCiMgQ291bnRzCmxvYWQoImRhdGFfbWF5MjAxOS9wc19tYXkyMDE5LlJEYXRhIikKCiMgVGF4b25vbXkKbG9hZCgiZGF0YV9tYXkyMDE5L3RheGEuUkRhdGEiKQp0YXhhIDwtIGRhdGEudGFibGUoc2VxMTZzID0gcm93bmFtZXModGF4YSksCiAgICAgICAgICAgICAgICAgICB0YXhhKQoKIyBTYW1wbGVzCnNhbXBsZXMgPC0gcHNfbWF5MjAxOUBzYW1fZGF0YQpkYXRhdGFibGUoc2FtcGxlcywKICAgICAgICAgICAgICBvcHRpb25zID0gbGlzdChwYWdlTGVuZ3RoID0gbnJvdyhzYW1wbGVzKSkpCmBgYAoKIyBQcnVuZSBkYXRhClRoZSBPVFVzIHdlcmUgbWFwcGVkIHRvIEJhY3RlcmlhICg5OC4zNCUpLCBFdWthcnlvdGEgKDEuNDMlKSBhbmQgdW5kZWZpbmVkICgwLjIzJSkga2luZ2RvbXMuIAoKYGBge3IgY2hlY2tfbWFwcGluZ19raW5nZG9tLCB3YXJuaW5nID0gRkFMU0UsIGVjaG8gPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFfQp0MSA8LSBkYXRhLnRhYmxlKHRhYmxlKHRheF90YWJsZShwc19tYXkyMDE5KVssCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJLaW5nZG9tIl0sCiAgICAgICAgICAgICAgICAgICAgICAgZXhjbHVkZSA9IE5VTEwpKQp0MSRWMVtpcy5uYSh0MSRWMSldIDwtICJVbmtub3duIgoKdDFbLCBwY3QgOj0gTi9zdW0oTildCnNldG9yZGVyKHQxLCAtTikKCmNvbG5hbWVzKHQxKSA8LSBjKCJLaW5nZG9tIiwKICAgICAgICAgICAgICAgICAgIk51bWJlciBvZiBPVFVzIiwKICAgICAgICAgICAgICAgICAgIlBlcmNlbnQgb2YgT1RVcyIpCmRhdGF0YWJsZSh0MSwKICAgICAgICAgIHJvd25hbWVzID0gRkFMU0UsCiAgICAgICAgICBjYXB0aW9uID0gIk51bWJlciBvZiBPVFVzIGJ5IEtpbmdkb20iLAogICAgICAgICAgY2xhc3MgPSAiY2VsbC1ib3JkZXIgc3RyaXBlIiwKICAgICAgICAgIG9wdGlvbnMgPSBsaXN0KHNlYXJjaCA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgcGFnZUxlbmd0aCA9IG5yb3codDEpKSkgJT4lCiAgZm9ybWF0Q3VycmVuY3koY29sdW1ucyA9IDIsCiAgICAgICAgICAgICAgICAgY3VycmVuY3kgPSAiIiwKICAgICAgICAgICAgICAgICBtYXJrID0gIiwiLAogICAgICAgICAgICAgICAgIGRpZ2l0cyA9IDApICU+JQogIGZvcm1hdFBlcmNlbnRhZ2UoY29sdW1ucyA9IDMsCiAgICAgICAgICAgICAgICAgICBkaWdpdHMgPSAyKQpgYGAKClRoZSB0b3RhbCBvZiA4LDEyOSB1bmlxdWUgc2VxdWVuY2VzIHdlcmUgZm91bmQuIE91dCBvZiB0aG9zZSwgNyw5OTQgd2VyZSBtYXBwZWQgdG8gYmFjdGVyaWFsIGdlbm9tZXMuIAoKYGBge3Iga2VlcF9iYWN0ZXJpYX0KZGltKHBzX21heTIwMTlAb3R1X3RhYmxlQC5EYXRhKQoKIyBSZW1vdmUgT1RVIHVubWFwcGVkIHRvIEJhY3RlcmlhCnBzMCA8LSBzdWJzZXRfdGF4YShwc19tYXkyMDE5LCAKICAgICAgICAgICAgICAgICAgIEtpbmdkb20gPT0gIkJhY3RlcmlhIikKZGltKHBzMEBvdHVfdGFibGVALkRhdGEpCmBgYAogIApUaGVzZSBiZWxvbmdlZCB0byAxMyBQaHlsdW0uIDIzMCBvZiB0aGUgT1RVcyAob3IgMi44OCUgb2YgYmFjdGVyaWFsIE9UVXMpIGNvdWxkIG5vdCBiZSBtYXBwZWQgdG8gYSBQaHlsYSBhbmQgd2VyZSByZW1vdmVkIGZyb20gdGhpcyBhbmFseXNpcyAod2l0aCA3LDc2NCBPVFVzIGxlZnQpLgoKYGBge3IgcGh5bHVtX21hcHBpbmd9CnQyIDwtIGRhdGEudGFibGUodGFibGUodGF4X3RhYmxlKHBzMClbLCAiUGh5bHVtIl0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleGNsdWRlID0gTlVMTCkpCnQyJFYxW2lzLm5hKHQyJFYxKV0gPC0gIlVua25vd24iCnNldG9yZGVyKHQyLCAtTikKdDJbLCBwY3QgOj0gTi9zdW0oTildCnNldG9yZGVyKHQyLCAtTikKCmNvbG5hbWVzKHQyKSA8LSBjKCJQaHlsdW0iLAogICAgICAgICAgICAgICAgICAiTnVtYmVyIG9mIE9UVXMiLAogICAgICAgICAgICAgICAgICAiUGVyY2VudCBvZiBPVFVzIikKCmRhdGF0YWJsZSh0MiwKICAgICAgICAgIHJvd25hbWVzID0gRkFMU0UsCiAgICAgICAgICBjYXB0aW9uID0gIk51bWJlciBvZiBCYWN0ZXJpYWwgT1RVcyBieSBQaHlsdW0iLAogICAgICAgICAgY2xhc3MgPSAiY2VsbC1ib3JkZXIgc3RyaXBlIiwKICAgICAgICAgIG9wdGlvbnMgPSBsaXN0KHNlYXJjaCA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgcGFnZUxlbmd0aCA9IG5yb3codDIpKSkgJT4lCiAgZm9ybWF0Q3VycmVuY3koY29sdW1ucyA9IDIsCiAgICAgICAgICAgICAgICAgY3VycmVuY3kgPSAiIiwKICAgICAgICAgICAgICAgICBtYXJrID0gIiwiLAogICAgICAgICAgICAgICAgIGRpZ2l0cyA9IDApICU+JQogIGZvcm1hdFBlcmNlbnRhZ2UoY29sdW1ucyA9IDMsCiAgICAgICAgICAgICAgICAgICBkaWdpdHMgPSAyKQoKcHMxIDwtIHN1YnNldF90YXhhKHBzMCwgCiAgICAgICAgICAgICAgICAgICAhaXMubmEoUGh5bHVtKSkKZGltKHBzMUBvdHVfdGFibGVALkRhdGEpCmBgYAoKIyBPVFUgdGFibGUgKGZpcnN0IDEwIHJvd3MpCmBgYHtyIG90dV90YWJsZSwgd2FybmluZz1GQUxTRSxlY2hvPUZBTFNFLG1lc3NhZ2U9RkFMU0V9Cm90dSA8LSBkYXRhLnRhYmxlKHBzMEB0YXhfdGFibGVALkRhdGEsCiAgICAgICAgICAgICAgICAgIHQocHMwQG90dV90YWJsZUAuRGF0YSkpCmRhdGF0YWJsZShoZWFkKG90dSwgMTApLAogICAgICAgICAgcm93bmFtZXMgPSBGQUxTRSwKICAgICAgICAgIGNhcHRpb24gPSAiVGF4b25vbWljICBjb3VudCB0YWJsZSIsCiAgICAgICAgICBjbGFzcyA9ICJjZWxsLWJvcmRlciBzdHJpcGUiLAogICAgICAgICAgb3B0aW9ucyA9IGxpc3Qoc2VhcmNoID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICBwYWdlTGVuZ3RoID0gMTApKSAlPiUKICBmb3JtYXRDdXJyZW5jeShjb2x1bW5zID0gNzozNiwKICAgICAgICAgICAgICAgICBjdXJyZW5jeSA9ICIiLAogICAgICAgICAgICAgICAgIG1hcmsgPSAiLCIsCiAgICAgICAgICAgICAgICAgZGlnaXRzID0gMCkKYGBgCgojIFRvdGFsIGNvdW50cyBwZXIgc2FtcGxlIChpLmUuIHNlcXVlbmNpbmcgZGVwdGgpCmBgYHtyIFRheCwgd2FybmluZz1GQUxTRSxlY2hvPUZBTFNFLG1lc3NhZ2U9RkFMU0UsZmlnLndpZHRoPTEwLGZpZy5oZWlnaHQ9NX0KdDEgPC0gY29sU3VtcyhvdHVbLCA3Om5jb2wob3R1KV0pCnQxIDwtIGRhdGEudGFibGUoU0FNUExFX05BTUUgPSBuYW1lcyh0MSksCiAgICAgICAgICAgICAgICAgVG90YWwgPSB0MSkKCnRtcCA8LSBkYXRhLnRhYmxlKFNBTVBMRV9OQU1FID0gc2FtcGxlcyRTQU1QTEVfTkFNRSwKICAgICAgICAgICAgICAgICAgVFJFQVRNRU5UID0gc2FtcGxlcyRUUkVBVE1FTlQsCiAgICAgICAgICAgICAgICAgIFdFRUsgPSBzYW1wbGVzJFdFRUspCgpzbXBsIDwtIG1lcmdlKHRtcCwKICAgICAgICAgICAgdDEsCiAgICAgICAgICAgIGJ5ID0gIlNBTVBMRV9OQU1FIikKCnAxIDwtIGdncGxvdChzbXBsLAogICAgICAgICAgICAgYWVzKHggPSBTQU1QTEVfTkFNRSwKICAgICAgICAgICAgICAgICB5ID0gVG90YWwsCiAgICAgICAgICAgICAgICAgZmlsbCA9IFRSRUFUTUVOVCwKICAgICAgICAgICAgICAgICBjb2xvdXIgPSBXRUVLKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgc2NhbGVfeF9kaXNjcmV0ZSgiU2FtcGxlIE5hbWUiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKCJOdW1iZXIgb2YgUmVhZHMiKSArCiAgc2NhbGVfZmlsbF9kaXNjcmV0ZSgiR3JvdXAiKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoanVzdCA9IDEpKSAKZ2dwbG90bHkocDEpCmBgYAoKYGBge3Igc2VxX2RlcHRoX2dyZXlzY2FsZSwgLCBmaWcud2lkdGggPSA2LCBmaWcuaGVpZ2h0ID0gNH0KdG1wIDwtIGNvcHkoc21wbCkKdG1wJFdFRUsgPC0gZmFjdG9yKHRtcCRXRUVLLAogICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoIndlZWsgMCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAid2VlayAxIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJ3ZWVrIDQiKSwKICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJXZWVrIDAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIldlZWsgMSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiV2VlayA0IikpCgp0bXAkVFJFQVRNRU5UIDwtIGZhY3Rvcih0bXAkVFJFQVRNRU5ULAogICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJDb250cm9sIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUEVJVEMiKSwKICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiQUlOOTNNIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUEVJVEMiKSkKcDEgPC0gZ2dwbG90KHRtcCwKICAgICAgICAgICAgIGFlcyh4ID0gU0FNUExFX05BTUUsCiAgICAgICAgICAgICAgICAgeSA9IFRvdGFsLAogICAgICAgICAgICAgICAgIGdyb3VwID0gVFJFQVRNRU5ULAogICAgICAgICAgICAgICAgIGZpbGwgPSBUUkVBVE1FTlQpKSArCiAgZmFjZXRfd3JhcCh+IFdFRUssCiAgICAgICAgICAgICBzY2FsZSA9ICJmcmVlX3giKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsCiAgICAgICAgICAgY29sb3IgPSAiYmxhY2siKSArCiAgc2NhbGVfeF9kaXNjcmV0ZSgiIikgKwogIHNjYWxlX3lfY29udGludW91cygiTnVtYmVyIG9mIFJlYWRzIikgKwogIHNjYWxlX2ZpbGxfZ3JleSgiVHJlYXRtZW50IiwgCiAgICAgICAgICAgICAgICAgIHN0YXJ0ID0gMC4yLCAKICAgICAgICAgICAgICAgICAgZW5kID0gMC44LAogICAgICAgICAgICAgICAgICBuYS52YWx1ZSA9ICJyZWQiLAogICAgICAgICAgICAgICAgICBhZXN0aGV0aWNzID0gImZpbGwiKSArCiAgdGhlbWVfYncoKSArIAogIHRoZW1lKHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfYmxhbmsoKSwgCiAgICAgICAgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICBheGlzLnRpdGxlLng9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGV4dC54PWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzLng9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKQoKdGlmZihmaWxlbmFtZSA9ICJ0bXAvc2VxX2RlcHRoX21heTIwMTkudGlmZiIsCiAgICAgaGVpZ2h0ID0gNCwKICAgICB3aWR0aCA9IDYsCiAgICAgdW5pdHMgPSAiaW4iLAogICAgIHJlcyA9IDYwMCwKICAgICBjb21wcmVzc2lvbiA9ICJsencrcCIpCnByaW50KHAxKQpncmFwaGljcy5vZmYoKQoKcHJpbnQocDEpCmBgYAoKIyBSaWNobmVzcyAoQWxwaGEgZGl2ZXJzaXR5KQpTaGFubm9uJ3MgZGl2ZXJzaXR5IGluZGV4IHdhcyBjYWxjdWxhdGVkIGZvciBlYWNoIHNhbXBsZSBhbmQgcGxvdGVkIG92ZXIgdGltZSB1c2luZyB0aGUgNyw3NjQgZnJvbSB0aGUgMTMgUGh5bHVtIGFib3ZlLgoKYGBge3IgcmljaG5lc3MsIGZpZy53aWR0aCA9IDEwLGZpZy5oZWlnaHQgPSA1fQpwczBAc2FtX2RhdGEkRGlldF9XZWVrIDwtIHBhc3RlKHNhbXBsZXMkVFJFQVRNRU5ULAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZXMkV0VFSywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXAgPSAiXyIpCnBzMEBzYW1fZGF0YSRJRCA8LSBzdWJzdHIoeCA9IHBzMEBzYW1fZGF0YSRTQU1QTEVfTkFNRSwKICAgICAgICAgICAgICAgICAgICAgICAgICBzdGFydCA9IDIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgc3RvcCA9IDMpCnAxIDwtIHBsb3RfcmljaG5lc3MocHMwLAogICAgICAgICAgICAgICAgICAgIHggPSAiRGlldF9XZWVrIiwgCiAgICAgICAgICAgICAgICAgICAgbWVhc3VyZXMgPSAiU2hhbm5vbiIpICsKICAgIGdlb21fbGluZShhZXMoZ3JvdXAgPSBJRCksCiAgICAgICAgICAgIGNvbG9yID0gImJsYWNrIikgKwogIGdlb21fcG9pbnQoYWVzKGZpbGwgPSBJRCksCiAgICAgICAgICAgICBzaGFwZSA9IDIxLAogICAgICAgICAgICAgc2l6ZSA9IDMsCiAgICAgICAgICAgICBjb2xvciA9ICJibGFjayIpICsKICBzY2FsZV94X2Rpc2NyZXRlKCIiKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSAzMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoanVzdCA9IDEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmp1c3QgPSAxKSkKCmdncGxvdGx5KHAgPSBwMSwKICAgICAgICAgdG9vbHRpcCA9IGMoIklEIiwKICAgICAgICAgICAgICAgICAgICAgInZhbHVlIikpCgpwMSA8LSBwMSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKCnRpZmYoZmlsZW5hbWUgPSAidG1wL3d0X3NoYW5ub24udGlmZiIsCiAgICAgaGVpZ2h0ID0gNCwKICAgICB3aWR0aCA9IDUsCiAgICAgdW5pdHMgPSAiaW4iLAogICAgIHJlcyA9IDYwMCwKICAgICBjb21wcmVzc2lvbiA9ICJsencrcCIpCnByaW50KHAxKQpncmFwaGljcy5vZmYoKQpgYGAKCmBgYHtyIHRlc3RfcmljaG5lc3N9CnRtcCA8LSBkYXRhLnRhYmxlKHAxJGRhdGEpCnRtcFssIGRlbHRhIDo9IHZhbHVlW1dFRUsgPT0gIndlZWsgNCJdIC0gCiAgICAgIHZhbHVlW1dFRUsgPT0gIndlZWsgMCJdLAogICAgYnkgPSBJRF0KCnRtcDEgPC0gZHJvcGxldmVscyh1bmlxdWUodG1wW1dFRUsgJWluJSBjKCJ3ZWVrIDAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAid2VlayA0IiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjKCJ2YWx1ZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIldFRUsiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJUUkVBVE1FTlQiKV0pKQptMSA8LSBsbSh2YWx1ZSB+IFdFRUsqVFJFQVRNRU5ULAogICAgICAgICBkYXRhID0gdG1wMSkKcHJpbnQoIk1vZGVsMTogU2hhbm5vbidzIGluZGV4IGJ5IHRyZWF0bWVudCBhbmQgdGltZSIpCmFub3ZhKG0xKQoKdG1wMiA8LSBkcm9wbGV2ZWxzKHVuaXF1ZSh0bXBbV0VFSyA9PSAid2VlayAwIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMoImRlbHRhIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAidmFsdWUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJUUkVBVE1FTlQiKV0pKQptMiA8LSBsbShkZWx0YSB+IFRSRUFUTUVOVCwKICAgICAgICAgZGF0YSA9IHRtcDIpCnByaW50KCJNb2RlbDI6IFNoYW5ub24ncyBpbmRleCBkaWZmZXJlbmNlcyAoV2VlayA0IC0gV2VlayAwKSBieSB0cmVhdG1lbnQiKQphbm92YShtMikKCm0zIDwtIHdpbGNveC50ZXN0KGRlbHRhIH4gVFJFQVRNRU5ULAogICAgICAgICAgICBkYXRhID0gdG1wMikKcHJpbnQoIk1vZGVsMzogV2lsY294b24gdGVzdCBmb3IgU2hhbm5vbidzIGluZGV4IGRpZmZlcmVuY2VzIChXZWVrIDQgLSBXZWVrIDApIGJ5IHRyZWF0bWVudCIpCm0zCmBgYAogIApUaGUgcmVzdWx0cyBzaG93ZWQgdGhhdCBpbiA0IG91dCBvZiA1IGFuaW1hbHMgaW4gdGhlIFBFSVRDIGdyb3VwIGRpdmVyc2l0eSBpbmNyZWFzZWQgb3ZlciB0aGUgNCB3ZWVrcyBjb21wYXJlZCB0byB0aGUgYmFzZWxpbmUuIEF0IHRoZSBzYW1lIHRpbWUsIG9ubHkgMiBvdXQgb2YgNSBDb250cm9sIGFuaW1hbHMgaW5jcmVhc2VkIGl0cyBtaWNyb2JpYWwgZGl2ZXJzaXR5IGluIHRoZSBzYW1lIHBlcmlvZCBvZiB0aW1lLiBOT1RFOiB0aGVyZSB3YXMgbm8gc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIHRyZWF0bWVudCBncm91cHMgYXMgd2VsbCBhcyBvdmVyIHRpbWUgKHNlZSByZXN1bHRzIGFib3ZlKS4gIAogIAojIENvdW50cyBhdCBQaHlsdW0gbGV2ZWwKYGBge3IgY291bnRzX3AsIHdhcm5pbmc9RkFMU0UsZWNobz1GQUxTRSxtZXNzYWdlPUZBTFNFfQpjb3VudHNfcCA8LSBjb3VudHNfYnlfdGF4X3JhbmsoZHQxID0gb3R1LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWdncl9ieSA9ICJQaHlsdW0iKQpzZXRvcmRlcihjb3VudHNfcCwgLWAwQTFgKQpkYXRhdGFibGUoY291bnRzX3AsCiAgICAgICAgICByb3duYW1lcyA9IEZBTFNFLAogICAgICAgICAgY2FwdGlvbiA9ICJUYXhvbm9taWMgIGNvdW50IHRhYmxlIiwKICAgICAgICAgIGNsYXNzID0gImNlbGwtYm9yZGVyIHN0cmlwZSIsCiAgICAgICAgICBvcHRpb25zID0gbGlzdChzZWFyY2ggPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2VMZW5ndGggPSBucm93KGNvdW50c19wKSkpICU+JQogIGZvcm1hdEN1cnJlbmN5KGNvbHVtbnMgPSAyOm5jb2woY291bnRzX3ApLAogICAgICAgICAgICAgICAgIGN1cnJlbmN5ID0gIiIsCiAgICAgICAgICAgICAgICAgbWFyayA9ICIsIiwKICAgICAgICAgICAgICAgICBkaWdpdHMgPSAwKQpgYGAKCiMgUmVsYXRpdmUgYWJ1bmRhbmNlICglKSBhdCBQaHlsdW0gbGV2ZWwKYGBge3IgcmFfcCwgd2FybmluZz1GQUxTRSxlY2hvPUZBTFNFLG1lc3NhZ2U9RkFMU0V9CnJhX3AgPC0gcmFfYnlfdGF4X3JhbmsoY291bnRzID0gY291bnRzX3AsCiAgICAgICAgICAgICAgICAgICAgICAgcGN0ID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgZGlnaXQgPSA0KQoKZGF0YXRhYmxlKHJhX3AsCiAgICAgICAgICByb3duYW1lcyA9IEZBTFNFLAogICAgICAgICAgY2FwdGlvbiA9ICJUYXhvbm9taWMgIGNvdW50IHRhYmxlIiwKICAgICAgICAgIGNsYXNzID0gImNlbGwtYm9yZGVyIHN0cmlwZSIsCiAgICAgICAgICBvcHRpb25zID0gbGlzdChzZWFyY2ggPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2VMZW5ndGggPSBucm93KHJhX3ApKSkgJT4lCiAgZm9ybWF0UGVyY2VudGFnZShjb2x1bW5zID0gMjpuY29sKGNvdW50c19wKSwKICAgICAgICAgICAgICAgICAgIGRpZ2l0cyA9IDIpCmBgYAoKUmVtb3ZlIHBoeWxhIHdpdGggcmVsYXRpdmUgYWJ1bmRhbmNlIG9mID49IDElIGluIGxlc3MgdGhhbiAxMCUgb2Ygc2FtcGxlcy4KCmBgYHtyIHByZXZfcH0KdDEgPC0gZGF0YS50YWJsZShQaHlsdW0gPSByYV9wJFBoeWx1bSwKICAgICAgICAgICAgICAgICBgTnVtYmVyIG9mIFNhbXBsZXNgID0gcm93U3VtcyhyYV9wWywgMjpuY29sKHJhX3ApXSA+PSAwLjAxKSkKdDEkYFBlcmNlbnQgU2FtcGxlc2AgPC0gIHQxJGBOdW1iZXIgb2YgU2FtcGxlc2AvMzAKCnNldG9yZGVyKHQxLCAtYE51bWJlciBvZiBTYW1wbGVzYCkKZGF0YXRhYmxlKHQxLAogICAgICAgICAgcm93bmFtZXMgPSBGQUxTRSwKICAgICAgICAgIGNhcHRpb24gPSAiVGF4b25vbWljICBjb3VudCB0YWJsZSIsCiAgICAgICAgICBjbGFzcyA9ICJjZWxsLWJvcmRlciBzdHJpcGUiLAogICAgICAgICAgb3B0aW9ucyA9IGxpc3Qoc2VhcmNoID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICBwYWdlTGVuZ3RoID0gbnJvdyh0MSkpKSAlPiUKICBmb3JtYXRQZXJjZW50YWdlKGNvbHVtbnMgPSAzLAogICAgICAgICAgICAgICAgICAgZGlnaXRzID0gMSkKYGBgCgpIZW5jZSwgb25seSA2IG91dCBvZiAxMyBQaHlsYSB3ZXJlIHN0dWRpZWQgaW4gdGhpcyBhbmFseXNpczogQWN0aW5vYmFjdGVyaWEsIEJhY3Rlcm9pZGV0ZXMsIEZpcm1pY3V0ZXMsIFByb3Rlb2JhY3RlcmlhLCBUZW5lcmljdXRlcyBhbmQgVmVycnVjb21pY3JvYmlhLiBSZWxhdGl2ZSBhYnVuZGFuY2UgYXQgdGhlIG5leHQgdGF4b25vbWljIGxldmVsIChDbGFzcykgd2FzLCB0aGVyZWZvcmUsIGNvbXB1dGVkIHJlbGF0aXZlIHRvIHRoZSBzdW0gb2YgdGhlc2UgNiBQaHlsYS4KCmBgYHtyIGtlZXBfNl9waHlsYSwgd2FybmluZz1GQUxTRSxlY2hvPUZBTFNFLG1lc3NhZ2U9RkFMU0V9CmtlZXBfcCA8LSB0MSRQaHlsdW1bdDEkYFBlcmNlbnQgU2FtcGxlc2AgPj0gMC4xXQpwYXN0ZTAoa2VlcF9wLCBjb2xsYXBzZSA9ICIsICIpCgpwczEgPC0gc3Vic2V0X3RheGEocHMwLCAKICAgICAgICAgICAgICAgICAgIFBoeWx1bSAlaW4lIGtlZXBfcCApCm90dTEgPC0gZGF0YS50YWJsZShwczFAdGF4X3RhYmxlQC5EYXRhLAogICAgICAgICAgICAgICAgICAgdChwczFAb3R1X3RhYmxlQC5EYXRhKSkKCmRhdGF0YWJsZShoZWFkKG90dTEsIDEwKSwKICAgICAgICAgIHJvd25hbWVzID0gRkFMU0UsCiAgICAgICAgICBjYXB0aW9uID0gIlRheG9ub21pYyAgY291bnQgdGFibGUiLAogICAgICAgICAgY2xhc3MgPSAiY2VsbC1ib3JkZXIgc3RyaXBlIiwKICAgICAgICAgIG9wdGlvbnMgPSBsaXN0KHNlYXJjaCA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgcGFnZUxlbmd0aCA9IDEwKSkgJT4lCiAgZm9ybWF0Q3VycmVuY3koY29sdW1ucyA9IDc6bmNvbChvdHUxKSwKICAgICAgICAgICAgICAgICBjdXJyZW5jeSA9ICIiLAogICAgICAgICAgICAgICAgIG1hcmsgPSAiLCIsCiAgICAgICAgICAgICAgICAgZGlnaXRzID0gMCkKYGBgCgo3LDYyOCBPVFVzLCBkb3duIGZyb20gNyw3NjQgT1RVcyBpbiB0aGUgcHJldmlvdXMgdGFibGUuCgoKIyBSZWxhdGl2ZSBBYnVuZGFuY2UgaW4gU2FtcGxlcyBhdCBEaWZmZXJlbnQgVGF4b25vbWljIFJhbmtzCiMjIDEuIENsYXNzCmBgYHtyIGNvdW50c19jLCB3YXJuaW5nPUZBTFNFLGVjaG89RkFMU0UsbWVzc2FnZT1GQUxTRSxmaWcud2lkdGg9MTAsZmlnLmhlaWdodD02fQpjb3VudHNfYyA8LSBjb3VudHNfYnlfdGF4X3JhbmsoZHQxID0gb3R1MSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFnZ3JfYnkgPSAiQ2xhc3MiKQpyYV9jIDwtIHJhX2J5X3RheF9yYW5rKGNvdW50c19jKQoKdGF4LnJhbmtzIDwtIHVuaXF1ZShvdHUxWywgYygiUGh5bHVtIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ2xhc3MiKV0pCgpyYV9jIDwtIG1lcmdlKHRheC5yYW5rcywKICAgICAgICAgICAgICByYV9jLAogICAgICAgICAgICAgIGJ5ID0gIkNsYXNzIikKCnRvdGFsIDwtIHJvd1N1bXMocmFfY1ssIDM6bmNvbChyYV9jKV0pCgpyYV9jJENsYXNzIDwtIGZhY3RvcihyYV9jJENsYXNzLAogICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSByYV9jJENsYXNzW29yZGVyKHRvdGFsKV0pCgpyYV9jJFBoeWx1bSA8LSBmYWN0b3IocmFfYyRQaHlsdW0sCiAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSB1bmlxdWUocmFfYyRQaHlsdW1bb3JkZXIodG90YWwpXSkpCnRtcCA8LSBtZWx0LmRhdGEudGFibGUoZGF0YSA9IHJhX2MsCiAgICAgICAgICAgICAgICAgICAgICAgaWQudmFycyA9IDE6MiwKICAgICAgICAgICAgICAgICAgICAgICBtZWFzdXJlLnZhcnMgPSAzOm5jb2woY291bnRzX2MpLAogICAgICAgICAgICAgICAgICAgICAgIHZhcmlhYmxlLm5hbWUgPSAiU0FNUExFX05BTUUiLAogICAgICAgICAgICAgICAgICAgICAgIHZhbHVlLm5hbWUgPSAiUkEiKQoKdG1wIDwtIG1lcmdlKGRhdGEudGFibGUoU0FNUExFX05BTUUgPSBzYW1wbGVzJFNBTVBMRV9OQU1FLAogICAgICAgICAgICAgICAgICAgICAgICBXRUVLID0gc2FtcGxlcyRXRUVLLAogICAgICAgICAgICAgICAgICAgICAgICBUUkVBVE1FTlQgPSBzYW1wbGVzJFRSRUFUTUVOVCksCiAgICAgICAgICAgICB0bXAsCiAgICAgICAgICAgICBieSA9ICJTQU1QTEVfTkFNRSIpCgojIFBsb3Qgc2FtcGxlcwpwMSA8LSBnZ3Bsb3QodG1wLAogICAgICAgICAgICAgYWVzKHggPSBTQU1QTEVfTkFNRSwKICAgICAgICAgICAgICAgICB5ID0gUkEsCiAgICAgICAgICAgICAgICAgZmlsbCA9IENsYXNzLAogICAgICAgICAgICAgICAgIGNvbG9yID0gUGh5bHVtKSkgKwogIGZhY2V0X3dyYXAofiBXRUVLICsgVFJFQVRNRU5ULAogICAgICAgICAgICAgc2NhbGVzID0gImZyZWVfeCIsCiAgICAgICAgICAgICBucm93ID0gMykgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgc2NhbGVfeF9kaXNjcmV0ZSgiIikgKwogIHNjYWxlX3lfY29udGludW91cyhleHBhbmQgPSBjKDAsIDApKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSAwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhqdXN0ID0gMSkpCmdncGxvdGx5KHAxKQpgYGAKCmBgYHtyIG1lYW5zX2MsIGVjaG8gPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0V9CmxyYSA8LSByYV9tZWx0KHJhID0gcmFfYywKICAgICAgICAgICAgICAgc2FtcGxlcyA9IHNhbXBsZXMsCiAgICAgICAgICAgICAgIHNhbXBsZV9uYW1lID0gIlNBTVBMRV9OQU1FIikKCm11IDwtIGRhdGEudGFibGUoYWdncmVnYXRlKGxyYSRSQSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgYnkgPSBsaXN0KFdlZWsgPSBscmEkV0VFSywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyZWF0bWVudCA9IGxyYSRUUkVBVE1FTlQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDbGFzcyA9IGxyYSRDbGFzcyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgIEZVTiA9ICJtZWFuIikpCm11WywgdG90YWwgOj0gc3VtKHgpLAogICBieSA9ICJDbGFzcyJdCnVsIDwtIHVuaXF1ZShtdVssIGMoIkNsYXNzIiwgCiAgICAgICAgICAgICAgICAgICAgInRvdGFsIildKQp1bCA8LSB1bFtvcmRlcih0b3RhbCksXQptdSRDbGFzcyA8LSBmYWN0b3IobXUkQ2xhc3MsCiAgICAgICAgICAgICAgICAgICBsZXZlbCA9IHVsJENsYXNzKQptdSR0b3RhbCA8LSBOVUxMCgpkYXRhdGFibGUobXUsCiAgICAgICAgICByb3duYW1lcyA9IEZBTFNFLAogICAgICAgICAgY2FwdGlvbiA9ICJUYXhvbm9taWMgIGNvdW50IHRhYmxlIiwKICAgICAgICAgIGNsYXNzID0gImNlbGwtYm9yZGVyIHN0cmlwZSIsCiAgICAgICAgICBvcHRpb25zID0gbGlzdChzZWFyY2ggPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2VMZW5ndGggPSBucm93KG11KSwKICAgICAgICAgICAgICAgICAgICAgICAgIG9yZGVyID0gbGlzdChsaXN0KDMsICdkZXNjJykpKSkKYGBgCgoKYGBge3IgbWVhbnNfY19wMCwgZmlnLndpZHRoID0gNywgZmlnLmhlaWdodCA9IDV9CnAwIDwtIGdncGxvdChtdSwKICAgICAgICAgICAgIGFlcyh4ID0gV2VlaywKICAgICAgICAgICAgICAgICB5ID0geCwKICAgICAgICAgICAgICAgICBncm91cCA9IFRyZWF0bWVudCkpICsKICBmYWNldF93cmFwKH4gQ2xhc3MsCiAgICAgICAgICAgICBzY2FsZSA9ICJmcmVlX3kiKSArCiAgZ2VvbV9saW5lKCkgKwogIGdlb21fcG9pbnQoYWVzKHNoYXBlID0gVHJlYXRtZW50LAogICAgICAgICAgICAgICAgIGNvbG9yID0gVHJlYXRtZW50KSwKICAgICAgICAgICAgIHNpemUgPSAzLAogICAgICAgICAgICAgYWxwaGEgPSAwLjUpICsKICBzY2FsZV94X2Rpc2NyZXRlKCIiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKCJSZWxhdGl2ZSBBYnVuZGFuY2UgKCUpIikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGp1c3QgPSAxKSkKCnRpZmYoZmlsZW5hbWUgPSAidG1wL3d0X2NsYXNzX292ZXJfdGltZS50aWZmIiwKICAgICBoZWlnaHQgPSA1LAogICAgIHdpZHRoID0gNywKICAgICB1bml0cyA9ICJpbiIsCiAgICAgcmVzID0gNjAwLAogICAgIGNvbXByZXNzaW9uID0gImx6dytwIikKcHJpbnQocDApCmdyYXBoaWNzLm9mZigpCgpwcmludChwMCkKYGBgCgoKYGBge3IgbWVhbnNfY19wMSwgZmlnLmhlaWdodCA9IDUsIGZpZy53aWR0aCA9IDZ9CnAxIDwtIGdncGxvdChtdSwKICAgICAgICAgICAgIGFlcyh4ID0geCwKICAgICAgICAgICAgICAgICB5ID0gQ2xhc3MsCiAgICAgICAgICAgICAgICAgY29sb3IgPSBUcmVhdG1lbnQsCiAgICAgICAgICAgICAgICAgc2hhcGUgPSBXZWVrKSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDMsCiAgICAgICAgICAgICBhbHBoYSA9IDAuNSkgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDEsCiAgICAgICAgICAgICBsaW5ldHlwZSA9ICJkYXNoZWQiKSArCiAgc2NhbGVfeF9jb250aW51b3VzKCJSZWxhdGl2ZSBBYnVuZGFuY2UgKCUpIikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKQoKdGlmZihmaWxlbmFtZSA9ICJ0bXAvd3RfY2xhc3NfcmEudGlmZiIsCiAgICAgaGVpZ2h0ID0gNCwKICAgICB3aWR0aCA9IDcsCiAgICAgdW5pdHMgPSAiaW4iLAogICAgIHJlcyA9IDYwMCwKICAgICBjb21wcmVzc2lvbiA9ICJsencrcCIpCnByaW50KHAxKQpncmFwaGljcy5vZmYoKQoKZ2dwbG90bHkocDEpCmBgYAoKIyMgMi4gT3JkZXIKYGBge3IgY291bnRzX28sIHdhcm5pbmc9RkFMU0UsZWNobz1GQUxTRSxtZXNzYWdlPUZBTFNFLGZpZy53aWR0aD0xMCxmaWcuaGVpZ2h0PTZ9CmNvdW50c19vIDwtIGNvdW50c19ieV90YXhfcmFuayhkdDEgPSBvdHUxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWdncl9ieSA9ICJPcmRlciIpCnJhX28gPC0gcmFfYnlfdGF4X3JhbmsoY291bnRzX28pCgp0YXgucmFua3MgPC0gdW5pcXVlKG90dTFbLCBjKCJQaHlsdW0iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICJPcmRlciIpXSkKCnJhX28gPC0gbWVyZ2UodGF4LnJhbmtzLAogICAgICAgICAgICAgIHJhX28sCiAgICAgICAgICAgICAgYnkgPSAiT3JkZXIiKQoKdG90YWwgPC0gcm93U3VtcyhyYV9vWywgMzpuY29sKHJhX28pXSkKCnJhX28kT3JkZXIgPC0gZmFjdG9yKHJhX28kT3JkZXIsCiAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IHJhX28kT3JkZXJbb3JkZXIodG90YWwpXSkKCnJhX28kUGh5bHVtIDwtIGZhY3RvcihyYV9vJFBoeWx1bSwKICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IHVuaXF1ZShyYV9vJFBoeWx1bVtvcmRlcih0b3RhbCldKSkKdG1wIDwtIG1lbHQuZGF0YS50YWJsZShkYXRhID0gcmFfbywKICAgICAgICAgICAgICAgICAgICAgICBpZC52YXJzID0gMToyLAogICAgICAgICAgICAgICAgICAgICAgIG1lYXN1cmUudmFycyA9IDM6bmNvbChjb3VudHNfbyksCiAgICAgICAgICAgICAgICAgICAgICAgdmFyaWFibGUubmFtZSA9ICJTQU1QTEVfTkFNRSIsCiAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUubmFtZSA9ICJSQSIpCgp0bXAgPC0gbWVyZ2UoZGF0YS50YWJsZShTQU1QTEVfTkFNRSA9IHNhbXBsZXMkU0FNUExFX05BTUUsCiAgICAgICAgICAgICAgICAgICAgICAgIFdFRUsgPSBzYW1wbGVzJFdFRUssCiAgICAgICAgICAgICAgICAgICAgICAgIFRSRUFUTUVOVCA9IHNhbXBsZXMkVFJFQVRNRU5UKSwKICAgICAgICAgICAgIHRtcCwKICAgICAgICAgICAgIGJ5ID0gIlNBTVBMRV9OQU1FIikKCiMgUGxvdCBzYW1wbGVzCnAxIDwtIGdncGxvdCh0bXAsCiAgICAgICAgICAgICBhZXMoeCA9IFNBTVBMRV9OQU1FLAogICAgICAgICAgICAgICAgIHkgPSBSQSwKICAgICAgICAgICAgICAgICBmaWxsID0gT3JkZXIsCiAgICAgICAgICAgICAgICAgY29sb3IgPSBQaHlsdW0pKSArCiAgZmFjZXRfd3JhcCh+IFdFRUsgKyBUUkVBVE1FTlQsCiAgICAgICAgICAgICBzY2FsZXMgPSAiZnJlZV94IiwKICAgICAgICAgICAgIG5yb3cgPSAzKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKICBzY2FsZV94X2Rpc2NyZXRlKCIiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZCA9IGMoMCwgMCkpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGp1c3QgPSAxKSkKZ2dwbG90bHkocDEpCmBgYAoKYGBge3IgbWVhbnNfbywgZWNobyA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRX0KbHJhIDwtIHJhX21lbHQocmEgPSByYV9vLAogICAgICAgICAgICAgICBzYW1wbGVzID0gc2FtcGxlcywKICAgICAgICAgICAgICAgc2FtcGxlX25hbWUgPSAiU0FNUExFX05BTUUiKQoKbXUgPC0gZGF0YS50YWJsZShhZ2dyZWdhdGUobHJhJFJBLAogICAgICAgICAgICAgICAgICAgICAgICAgICBieSA9IGxpc3QoV2VlayA9IGxyYSRXRUVLLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJlYXRtZW50ID0gbHJhJFRSRUFUTUVOVCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE9yZGVyID0gbHJhJE9yZGVyKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgRlVOID0gIm1lYW4iKSkKbXVbLCB0b3RhbCA6PSBzdW0oeCksCiAgIGJ5ID0gIk9yZGVyIl0KdWwgPC0gdW5pcXVlKG11WywgYygiT3JkZXIiLCAKICAgICAgICAgICAgICAgICAgICAidG90YWwiKV0pCnVsIDwtIHVsW29yZGVyKHRvdGFsKSxdCm11JE9yZGVyIDwtIGZhY3RvcihtdSRPcmRlciwKICAgICAgICAgICAgICAgICAgIGxldmVsID0gdWwkT3JkZXIpCm11JHRvdGFsIDwtIE5VTEwKCmRhdGF0YWJsZShtdSwKICAgICAgICAgIHJvd25hbWVzID0gRkFMU0UsCiAgICAgICAgICBjYXB0aW9uID0gIlRheG9ub21pYyAgY291bnQgdGFibGUiLAogICAgICAgICAgY2xhc3MgPSAiY2VsbC1ib3JkZXIgc3RyaXBlIiwKICAgICAgICAgIG9wdGlvbnMgPSBsaXN0KHNlYXJjaCA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgcGFnZUxlbmd0aCA9IG5yb3cobXUpLAogICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXIgPSBsaXN0KGxpc3QoMywgJ2Rlc2MnKSkpKQpgYGAKCmBgYHtyIG1lYW5zX29fcDAsIGZpZy53aWR0aCA9IDEwLCBmaWcuaGVpZ2h0ID0gNX0KcDAgPC0gZ2dwbG90KG11LAogICAgICAgICAgICAgYWVzKHggPSBXZWVrLAogICAgICAgICAgICAgICAgIHkgPSB4LAogICAgICAgICAgICAgICAgIGdyb3VwID0gVHJlYXRtZW50KSkgKwogIGZhY2V0X3dyYXAofiBPcmRlciwKICAgICAgICAgICAgIHNjYWxlID0gImZyZWVfeSIpICsKICBnZW9tX2xpbmUoKSArCiAgZ2VvbV9wb2ludChhZXMoc2hhcGUgPSBUcmVhdG1lbnQsCiAgICAgICAgICAgICAgICAgY29sb3IgPSBUcmVhdG1lbnQpLAogICAgICAgICAgICAgc2l6ZSA9IDUsCiAgICAgICAgICAgICBhbHBoYSA9IDAuNSkKcHJpbnQocDApCmBgYAoKYGBge3IgbWVhbnNfb19wMSwgZmlnLndpZHRoID0gMTAsIGZpZy5oZWlnaHQgPSAxMH0KcDEgPC0gZ2dwbG90KG11LAogICAgICAgICAgICAgYWVzKHggPSB4LAogICAgICAgICAgICAgICAgIHkgPSBPcmRlciwKICAgICAgICAgICAgICAgICBmaWxsID0gVHJlYXRtZW50LAogICAgICAgICAgICAgICAgIHNoYXBlID0gV2VlaykpICsKICAjIGZhY2V0X3dyYXAofiBTZXgsIG5yb3cgPSAxKSArCiAgZ2VvbV9wb2ludChzaXplID0gMywKICAgICAgICAgICAgIGFscGhhID0gMC41KSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMSwKICAgICAgICAgICAgIGxpbmV0eXBlID0gImRhc2hlZCIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoIlJlbGF0aXZlIEFidW5kYW5jZSAoJSkiKQpnZ3Bsb3RseShwMSkKYGBgCgojIFNlc3Npb24gSW5mb3JtYXRpb24KYGBge3IgaW5mbyxldmFsPVRSVUV9CnNlc3Npb25JbmZvKCkKYGBg